#!/usr/bin/env python3
"""
报告模板引擎系统
提供稳定、专业的报告生成功能
"""

import os
import json
from datetime import datetime
from jinja2 import Environment, FileSystemLoader, select_autoescape


class ReportTemplateEngine:
    """报告模板引擎类"""
    
    def __init__(self, templates_dir=None):
        """初始化模板引擎"""
        if templates_dir is None:
            templates_dir = os.path.join(os.path.dirname(__file__), 'html')
        
        self.templates_dir = templates_dir
        self.env = Environment(
            loader=FileSystemLoader(templates_dir),
            autoescape=select_autoescape(['html', 'xml'])
        )
        
        # 注册自定义过滤器
        self.env.filters['format_number'] = self._format_number
        self.env.filters['format_percentage'] = self._format_percentage
        self.env.filters['format_duration'] = self._format_duration
        self.env.filters['format_date'] = self._format_date
    
    def _format_number(self, value):
        """格式化数字"""
        if isinstance(value, (int, float)):
            return f"{value:,.0f}"
        return str(value)
    
    def _format_percentage(self, value):
        """格式化百分比"""
        if isinstance(value, (int, float)):
            return f"{value:.1%}"
        return str(value)
    
    def _format_duration(self, minutes):
        """格式化时长（分钟转小时分钟）"""
        if isinstance(minutes, (int, float)):
            hours = int(minutes // 60)
            mins = int(minutes % 60)
            if hours > 0:
                return f"{hours}小时{mins}分钟"
            else:
                return f"{mins}分钟"
        return str(minutes)
    
    def _format_date(self, date_obj, format_str='%Y-%m-%d'):
        """格式化日期"""
        if isinstance(date_obj, datetime):
            return date_obj.strftime(format_str)
        elif isinstance(date_obj, str):
            return date_obj
        return str(date_obj)
    
    def render_report(self, report_type, data):
        """
        渲染报告
        
        Args:
            report_type: 报告类型 (single_project, single_region, multi_dimension, multi_region_single_project)
            data: 报告数据
        
        Returns:
            str: 渲染后的HTML内容
        """
        template_name = f"report_{report_type}.html"
        
        try:
            template = self.env.get_template(template_name)
            return template.render(data=data)
        except Exception as e:
            print(f"模板渲染失败: {str(e)}")
            # 回退到通用模板
            return self._render_fallback_template(data)
    
    def _render_fallback_template(self, data):
        """回退模板，确保总是能生成报告"""
        try:
            template = self.env.get_template("report_base.html")
            return template.render(data=data)
        except Exception as e:
            print(f"回退模板也失败: {str(e)}")
            return self._generate_minimal_html(data)
    
    def _generate_minimal_html(self, data):
        """生成最小化HTML（终极回退）"""
        return f"""
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <title>{data.get('title', '报告')}</title>
            <style>
                body {{ font-family: "Microsoft YaHei", Arial, sans-serif; margin: 40px; }}
                .error {{ color: red; padding: 20px; border: 1px solid red; }}
            </style>
        </head>
        <body>
            <div class="error">
                <h1>报告生成出现问题</h1>
                <p>模板系统暂时不可用，请联系技术人员。</p>
                <p>报告标题: {data.get('title', '未知')}</p>
                <p>生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
            </div>
        </body>
        </html>
        """


def prepare_report_data(summary, data_structure, ai_content, member_name, start_time, end_time):
    """
    准备报告数据，转换为模板友好的格式
    
    Args:
        summary: 统计摘要
        data_structure: 数据结构信息
        ai_content: AI生成的内容
        member_name: 机构名称
        start_time: 开始时间
        end_time: 结束时间
    
    Returns:
        dict: 格式化的报告数据
    """
    
    # 解析AI内容
    content_sections = parse_ai_content(ai_content)
    
    # 基础报告数据结构
    base_data = {
        # 基础信息
        'title': f"{member_name} 清洁设备工作分析报告",
        'subtitle': f"{start_time.strftime('%Y年%m月%d日')} 至 {end_time.strftime('%Y年%m月%d日')}",
        'report_type': data_structure['report_type'],
        'report_focus': data_structure['focus'],
        'generation_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
        
        # 统计数据
        'basic_stats': {
            'total_devices': summary['basic_stats']['total_devices'],
            'total_regions': summary['basic_stats']['total_regions'],
            'total_projects': summary['basic_stats']['total_projects'],
            'period_days': (end_time - start_time).days + 1
        },
        
        # 出勤统计
        'attendance_stats': {
            'overall_rate': summary['attendance_stats']['overall_attendance_rate'],
            'expected_days': summary['attendance_stats']['total_expected_days'],
            'actual_days': summary['attendance_stats']['total_actual_days'],
            'region_data': summary['attendance_stats']['region_attendance']
        },
        
        # 设备统计
        'device_stats': summary['device_stats'],
        
        # 排名数据
        'rankings': summary.get('rankings', {}),
        
        # 异常设备
        'anomaly_devices': summary['anomaly_devices'],
        
        # AI生成的内容
        'content_sections': content_sections,
        
        # 图表数据
        'charts': generate_chart_data(summary),
        
        # 区域和项目列表
        'regions': summary['basic_stats'].get('region_list', []),
        'projects': summary['basic_stats'].get('project_list', [])
    }
    
    # 根据报告类型添加特定数据
    if data_structure['report_type'] == 'single_region':
        base_data.update(prepare_single_region_data(summary))
    elif data_structure['report_type'] == 'multi_dimension':
        base_data.update(prepare_multi_dimension_data(summary))
    elif data_structure['report_type'] == 'multi_region_single_project':
        base_data.update(prepare_multi_region_data(summary))
    
    return base_data


def parse_ai_content(ai_content):
    """
    解析AI生成的内容，提取结构化信息并保持段落完整性
    
    Args:
        ai_content: AI生成的原始内容
    
    Returns:
        dict: 解析后的内容结构
    """
    sections = {}
    
    # 按段落分割内容，保持段落完整性
    paragraphs = [p.strip() for p in ai_content.split('\n\n') if p.strip()]
    
    current_section = None
    current_content = []
    
    for paragraph in paragraphs:
        # 检测章节标题
        if any(keyword in paragraph for keyword in ['第一部分', '第二部分', '第三部分', '第四部分', '第五部分', '第六部分']):
            # 保存前一章节
            if current_section and current_content:
                sections[current_section] = '<br><br>'.join(current_content)
            
            # 开始新章节，提取标题
            lines = paragraph.split('\n')
            title_line = lines[0].strip()
            current_section = title_line
            
            # 如果标题后面还有内容，作为第一个段落
            remaining_content = '\n'.join(lines[1:]).strip()
            current_content = [remaining_content] if remaining_content else []
        else:
            # 添加到当前章节
            if current_section:
                # 处理段落内部的换行，保持段落结构
                formatted_paragraph = paragraph.replace('\n', '<br>')
                current_content.append(formatted_paragraph)
            else:
                # 如果还没有章节标题，检查是否是隐含的章节开始
                if '总结' in paragraph or '概况' in paragraph or '分析' in paragraph:
                    current_section = '主要分析内容'
                    formatted_paragraph = paragraph.replace('\n', '<br>')
                    current_content = [formatted_paragraph]
    
    # 保存最后一章节
    if current_section and current_content:
        sections[current_section] = '<br><br>'.join(current_content)
    
    # 如果没有找到章节，将整个内容作为主要内容，但保持段落结构
    if not sections:
        formatted_content = '<br><br>'.join([p.replace('\n', '<br>') for p in paragraphs])
        sections['主要分析内容'] = formatted_content
    
    return sections


def generate_chart_data(summary):
    """
    生成图表数据
    
    Args:
        summary: 统计摘要
    
    Returns:
        dict: 图表数据
    """
    charts = {}
    
    # 出勤率饼图数据
    if summary['attendance_stats']['region_attendance']:
        charts['attendance_pie'] = {
            'title': '各区域出勤率分布',
            'data': [
                {
                    'name': item['region_name'],
                    'value': item.get('大区出勤率', 0)
                }
                for item in summary['attendance_stats']['region_attendance']
            ]
        }
    
    # 设备工作时间柱状图
    if summary.get('device_stats'):
        top_devices = sorted(summary['device_stats'], key=lambda x: x.get('总工作时间', 0), reverse=True)[:10]
        charts['device_worktime_bar'] = {
            'title': '设备工作时间排名(前10)',
            'data': [
                {
                    'name': item['imei'][-6:],  # 只显示后6位
                    'value': item.get('总工作时间', 0)
                }
                for item in top_devices
            ]
        }
    
    return charts


# 全局模板引擎实例
template_engine = ReportTemplateEngine()


def prepare_single_region_data(summary):
    """准备单区域报告特定数据"""
    # 从区域出勤数据中获取区域名称
    region_name = '未知区域'
    if summary['attendance_stats']['region_attendance']:
        region_name = summary['attendance_stats']['region_attendance'][0].get('region_name', '未知区域')
    
    # 准备项目分布数据
    project_distribution = []
    if summary.get('rankings', {}).get('top_projects'):
        # 如果有项目排名数据，从中构建项目分布
        all_projects = summary['rankings']['top_projects'] + summary['rankings'].get('bottom_projects', [])
        for project in all_projects:
            project_distribution.append({
                'project_name': project.get('project_name', '未知项目'),
                'device_count': 0,  # 需要从设备数据中计算
                'work_days': project.get('工作天数', 0),
                'total_work_time': project.get('总工作时间', 0),
                'avg_work_time': project.get('平均工作时间', 0),
                'efficiency': project.get('总工作时间', 0) / max(project.get('工作天数', 1), 1) / 8  # 假设8小时工作制
            })
    
    # 准备设备类型分析
    device_type_analysis = []
    if summary.get('device_stats'):
        type_stats = {}
        for device in summary['device_stats']:
            device_type = device.get('type', '未知类型')
            if device_type not in type_stats:
                type_stats[device_type] = {
                    'type_name': device_type,
                    'count': 0,
                    'total_work_time': 0,
                    'devices': []
                }
            type_stats[device_type]['count'] += 1
            type_stats[device_type]['total_work_time'] += device.get('总工作时间', 0)
            type_stats[device_type]['devices'].append(device)
        
        total_devices = len(summary['device_stats'])
        for type_name, stats in type_stats.items():
            device_type_analysis.append({
                'type_name': type_name,
                'count': stats['count'],
                'percentage': stats['count'] / max(total_devices, 1),
                'total_work_time': stats['total_work_time'],
                'avg_work_time': stats['total_work_time'] / max(stats['count'], 1),
                'efficiency': min(stats['total_work_time'] / max(stats['count'], 1) / 480, 1)  # 假设8小时=480分钟
            })
    
    return {
        'region_overview': {
            'region_name': region_name,
            'device_count': summary['basic_stats']['total_devices'],
            'project_count': summary['basic_stats']['total_projects'],
            'efficiency': summary['attendance_stats']['overall_attendance_rate']
        },
        'project_distribution': project_distribution,
        'device_type_analysis': device_type_analysis,
        'time_distribution': [],  # 时间分布数据暂时为空，需要原始数据支持
        'project_rankings': summary.get('rankings', {})
    }


def prepare_multi_dimension_data(summary):
    """准备多维度报告特定数据"""
    # 计算数据点数量
    total_data_points = len(summary.get('device_stats', []))
    if summary['attendance_stats']['region_attendance']:
        total_data_points += len(summary['attendance_stats']['region_attendance'])
    
    # 准备区域维度数据
    region_dimension = []
    for region_data in summary['attendance_stats']['region_attendance']:
        region_dimension.append({
            'region_name': region_data.get('region_name', '未知区域'),
            'device_count': 0,  # 需要从设备数据中计算
            'efficiency': region_data.get('大区出勤率', 0),
            'attendance_rate': region_data.get('大区出勤率', 0),
            'failure_rate': 0.05,  # 模拟数据
            'score': region_data.get('大区出勤率', 0) * 100
        })
    
    # 准备项目维度数据
    project_dimension = []
    if summary.get('rankings', {}).get('top_projects'):
        all_projects = summary['rankings']['top_projects'] + summary['rankings'].get('bottom_projects', [])
        for project in all_projects:
            project_dimension.append({
                'project_name': project.get('project_name', '未知项目'),
                'region_name': '未知区域',  # 需要从原始数据获取
                'device_count': 0,  # 需要计算
                'work_intensity': min(project.get('总工作时间', 0) / max(project.get('工作天数', 1), 1) / 8, 1),
                'utilization': min(project.get('总工作时间', 0) / 480, 1),  # 假设8小时工作制
                'status': '正常' if project.get('总工作时间', 0) > 240 else '需关注'
            })
    
    # 准备设备类型维度数据
    device_type_dimension = []
    if summary.get('device_stats'):
        type_stats = {}
        for device in summary['device_stats']:
            device_type = device.get('type', '未知类型')
            if device_type not in type_stats:
                type_stats[device_type] = {
                    'type_name': device_type,
                    'count': 0,
                    'total_work_time': 0,
                    'devices': []
                }
            type_stats[device_type]['count'] += 1
            type_stats[device_type]['total_work_time'] += device.get('总工作时间', 0)
        
        for type_name, stats in type_stats.items():
            device_type_dimension.append({
                'type_name': type_name,
                'count': stats['count'],
                'avg_work_time': stats['total_work_time'] / max(stats['count'], 1),
                'reliability': 0.95,  # 模拟数据
                'maintenance_cost': stats['count'] * 1000,  # 模拟维护成本
                'roi': 2.5  # 模拟投资回报率
            })
    
    # 准备关键指标对比
    key_metrics_comparison = [
        {
            'metric_name': '整体出勤率',
            'current_value': f"{summary['attendance_stats']['overall_attendance_rate']:.1%}",
            'target_value': '85%',
            'completion_rate': summary['attendance_stats']['overall_attendance_rate'] / 0.85,
            'trend': '上升' if summary['attendance_stats']['overall_attendance_rate'] > 0.8 else '下降'
        },
        {
            'metric_name': '设备利用率',
            'current_value': f"{len([d for d in summary['device_stats'] if d.get('总工作时间', 0) > 0]) / max(len(summary['device_stats']), 1):.1%}",
            'target_value': '90%',
            'completion_rate': len([d for d in summary['device_stats'] if d.get('总工作时间', 0) > 0]) / max(len(summary['device_stats']), 1) / 0.9,
            'trend': '稳定'
        }
    ]
    
    return {
        'dimension_overview': {
            'analysis_dimensions': ['区域', '项目', '设备类型', '时间'],
            'total_data_points': total_data_points,
            'coverage_rate': 1.0,
            'overall_score': summary['attendance_stats']['overall_attendance_rate']
        },
        'region_dimension': region_dimension,
        'project_dimension': project_dimension,
        'device_type_dimension': device_type_dimension,
        'time_dimension': [],  # 时间维度数据需要原始数据支持
        'key_metrics_comparison': key_metrics_comparison,
        'multi_dimension_rankings': summary.get('rankings', {})
    }


def prepare_multi_region_data(summary):
    """准备多区域单项目报告特定数据"""
    # 获取项目名称
    project_name = '未知项目'
    if summary['basic_stats']['project_list']:
        project_name = summary['basic_stats']['project_list'][0]
    
    # 准备区域执行情况
    region_execution = []
    for region_data in summary['attendance_stats']['region_attendance']:
        region_execution.append({
            'region_name': region_data.get('region_name', '未知区域'),
            'device_count': 0,  # 需要从设备数据中计算
            'work_days': region_data.get('工作天数', 0),
            'total_work_time': region_data.get('工作天数', 0) * 480,  # 假设每天8小时
            'efficiency': region_data.get('大区出勤率', 0),
            'progress': region_data.get('大区出勤率', 0),
            'status': '正常' if region_data.get('大区出勤率', 0) > 0.8 else '需关注'
        })
    
    # 准备协调分析数据
    coordination_analysis = [
        {
            'coordination_item': '设备配置协调',
            'involved_regions': f"{summary['basic_stats']['total_regions']}个区域",
            'sync_level': 0.85,
            'resource_sharing': 0.75,
            'communication_efficiency': 0.90,
            'coordination_score': 85
        },
        {
            'coordination_item': '工作进度同步',
            'involved_regions': f"{summary['basic_stats']['total_regions']}个区域",
            'sync_level': summary['attendance_stats']['overall_attendance_rate'],
            'resource_sharing': 0.80,
            'communication_efficiency': 0.85,
            'coordination_score': summary['attendance_stats']['overall_attendance_rate'] * 100
        }
    ]
    
    # 准备设备流动性数据
    device_mobility = {
        'distribution': [],
        'transfer_records': []
    }
    
    # 为每个区域创建设备分布数据
    for region_data in summary['attendance_stats']['region_attendance']:
        device_mobility['distribution'].append({
            'region_name': region_data.get('region_name', '未知区域'),
            'allocated_devices': 0,  # 需要计算
            'active_devices': region_data.get('工作天数', 0),
            'mobile_devices': 0,
            'utilization': region_data.get('大区出勤率', 0),
            'mobility_frequency': 0.1
        })
    
    # 准备进度对比数据
    progress_comparison = [
        {
            'milestone_name': '第一阶段',
            'planned_progress': 0.25,
            'actual_progress': summary['attendance_stats']['overall_attendance_rate'] * 0.3,
            'deviation': (summary['attendance_stats']['overall_attendance_rate'] * 0.3 - 0.25) * 100,
            'risk_level': '低' if summary['attendance_stats']['overall_attendance_rate'] > 0.8 else '中',
            'suggestion': '按计划执行' if summary['attendance_stats']['overall_attendance_rate'] > 0.8 else '需加强管理'
        },
        {
            'milestone_name': '第二阶段',
            'planned_progress': 0.50,
            'actual_progress': summary['attendance_stats']['overall_attendance_rate'] * 0.6,
            'deviation': (summary['attendance_stats']['overall_attendance_rate'] * 0.6 - 0.50) * 100,
            'risk_level': '低' if summary['attendance_stats']['overall_attendance_rate'] > 0.8 else '中',
            'suggestion': '继续保持' if summary['attendance_stats']['overall_attendance_rate'] > 0.8 else '重点关注'
        }
    ]
    
    # 准备跨区域排名
    cross_region_rankings = {
        'region_ranking': []
    }
    
    for region_data in summary['attendance_stats']['region_attendance']:
        cross_region_rankings['region_ranking'].append({
            'region_name': region_data.get('region_name', '未知区域'),
            'total_score': region_data.get('大区出勤率', 0) * 100,
            'execution_efficiency': region_data.get('大区出勤率', 0),
            'coordination_ability': 0.85,  # 模拟数据
            'highlight': '出勤率表现优秀' if region_data.get('大区出勤率', 0) > 0.8 else '需提升出勤率'
        })
    
    # 按得分排序
    cross_region_rankings['region_ranking'].sort(key=lambda x: x['total_score'], reverse=True)
    
    return {
        'cross_region_overview': {
            'project_name': project_name,
            'region_count': summary['basic_stats']['total_regions'],
            'total_devices': summary['basic_stats']['total_devices'],
            'coordination_index': summary['attendance_stats']['overall_attendance_rate']
        },
        'region_execution': region_execution,
        'coordination_analysis': coordination_analysis,
        'device_mobility': device_mobility,
        'progress_comparison': progress_comparison,
        'cross_region_rankings': cross_region_rankings
    }


def create_simplified_ai_prompt(data_structure, summary_stats):
    """
    创建简化的AI提示词，专注于内容生成而非HTML格式
    
    Args:
        data_structure: 数据结构信息
        summary_stats: 统计摘要数据
    
    Returns:
        str: 简化的AI提示词
    """
    
    # 基础统计信息
    basic_info = f"""
分析对象：{data_structure['focus']}
报告类型：{data_structure['report_type']}
设备总数：{summary_stats['basic_stats']['total_devices']}台
区域数量：{summary_stats['basic_stats']['total_regions']}个
项目数量：{summary_stats['basic_stats']['total_projects']}个
整体出勤率：{summary_stats['attendance_stats']['overall_attendance_rate']:.1%}
"""
    
    # 异常情况
    anomaly_info = ""
    if summary_stats['anomaly_devices']['idle_count'] > 0:
        anomaly_info += f"完全缺勤设备：{summary_stats['anomaly_devices']['idle_count']}台\n"
    if summary_stats['anomaly_devices'].get('low_efficiency_devices'):
        anomaly_info += f"低效设备：{len(summary_stats['anomaly_devices']['low_efficiency_devices'])}台\n"
    
    prompt = f"""
请基于以下清洁设备运营数据，生成专业的分析报告内容。只需要生成文字内容，不需要HTML格式。

【基础数据】
{basic_info}

【异常情况】
{anomaly_info if anomaly_info else "设备运行状态良好，无明显异常。"}

请按以下结构生成分析内容，每个部分用明确的标题分隔，内容要形成完整的段落：

第一部分 - 数据概况总结
用2-3个完整段落概述统计期间的整体运营情况，包括设备使用率、出勤情况等核心指标的综合分析。

第二部分 - 关键发现
用段落形式阐述3-5个最重要的发现或趋势，每个发现用一个段落详细说明，避免使用条目式列举。如果有统计口径不一的先不要提了。

第三部分 - 问题识别
以段落形式深入分析当前存在的主要问题或风险点，说明问题的表现、影响和可能的原因。

第四部分 - 成效亮点
用段落形式总结表现良好的方面或改进成果，提供具体的数据支撑和分析。

第五部分 - 管理建议
以连续的段落形式提供具体的管理建议或改进措施，每个建议要有详细的实施方案和预期效果。

第六部分 - 下期重点
用段落形式建议下一阶段需要重点关注的事项，说明优先级和实施策略。

要求：
1. 每个部分都要写成完整的段落，不要使用条目列表
2. 段落之间要有逻辑连接，形成连贯的分析
3. 内容要专业、客观，基于数据说话
4. 语言流畅，避免机械式表述
5. 篇幅控制在800-1200字
"""
    
    return prompt


def render_stable_report(report_type, summary, data_structure, ai_content, member_name, start_time, end_time):
    """
    渲染稳定的报告
    
    Args:
        report_type: 报告类型
        summary: 统计摘要
        data_structure: 数据结构
        ai_content: AI内容
        member_name: 机构名称
        start_time: 开始时间
        end_time: 结束时间
    
    Returns:
        str: 渲染后的HTML
    """
    # 准备报告数据
    report_data = prepare_report_data(
        summary, data_structure, ai_content, 
        member_name, start_time, end_time
    )
    
    # 渲染报告
    return template_engine.render_report(report_type, report_data)